﻿using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using FrontDisplay.NativeMethods;
using Def.Log;

namespace FrontDisplay
{
    public static class Utility
    {
        public static Color Darker(this Color color)
        {
            Color result = color;
            result.R /= 5;
            result.G /= 5;
            result.B /= 5;
            return result;
        }

        public static Color Lighter(this Color color)
        {
            Color result = color;
            result.R = (byte)(Math.Min(result.R * 1.5, 255));
            result.G = (byte)(Math.Min(result.G * 1.5, 255));
            result.B = (byte)(Math.Min(result.B * 1.5, 255));
            return result;
        }

        public static void InvokedCall(this DispatcherObject control, Action action)
        {
            if (control.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
            {
                control.Dispatcher.Invoke(action);
            }
            else
            {
                action.Invoke();
            }
        }

        public static void InvokedCall<T>(this DispatcherObject control, Action<T> action, T parameter)
        {
            if (control.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
            {
                control.Dispatcher.Invoke(action, parameter);
            }
            else
            {
                action.Invoke(parameter);
            }
        }

        public static void InvokedCall<T1, T2>(this DispatcherObject control, Action<T1, T2> action, T1 parameter1, T2 parameter2)
        {
            if (control.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
            {
                control.Dispatcher.Invoke(action, parameter1, parameter2);
            }
            else
            {
                action.Invoke(parameter1, parameter2);
            }
        }

        public static void InvokedCall<T>(this DispatcherObject control, EventHandler<T> action, object sender, T eventArgs) where T : EventArgs
        {
            if (control.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
            {
                control.Dispatcher.Invoke(action, sender, eventArgs);
            }
            else
            {
                action.Invoke(sender, eventArgs);
            }
        }

        public static void AddExWindowStyle(this Window window, int exStyle)
        {
            WindowInteropHelper wndHelper = new WindowInteropHelper(window);

            int style = WinApi.GetWindowLong(wndHelper.Handle, WinApi.GWL_EXSTYLE);
            style |= exStyle;
            WinApi.SetWindowLong(wndHelper.Handle, WinApi.GWL_EXSTYLE, style);
        }

        //TODO: it takes a lot of time to download image (expecially if there are no such image on web server, it tries to download it again and again for every method run).
        //TODO: maybe it's better to make this method async.
        public static Image LoadImage(string imageName, string imagePath, string webImagePath, bool isDownload)
        {
            Image image = new Image();
            imagePath = Global.ApplicationDataFolder + imagePath + Path.AltDirectorySeparatorChar; //TODO: was Utility.MapPath(imagePath);

            if ((imageName != null) && (imageName.Trim().Length > 0))
            {
                try
                {
                    image.Source = new BitmapImage(new Uri(imagePath + imageName));
                }
                catch
                {
                    if (isDownload)
                    {
                        try
                        {
                            WebClient Client = new WebClient();
                            //new Uri(((System.Web.Services.Protocols.SoapHttpClientProtocol)Cms.Client.Global.Service).Url);
                            string url = webImagePath + imageName;
                            if (!Directory.Exists(imagePath))
                            {
                                Directory.CreateDirectory(imagePath);
                            }
                            Client.DownloadFile(url, imagePath + imageName);
                            image.Source = new BitmapImage(new Uri(imagePath + imageName));
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex);
                        }
                    }
                }
            }
            return image;
        }

        /// <summary>
        /// Returns the physical file path that corresponds to the specifiied path.
        /// </summary>
        /// <returns>the physical file path that corresponds to path.</returns>
        public static string MapPath(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            path = path.NormalizePath();

            if ((path.Length > 0) && (path[1] != ':'))
            {
                //if (HttpContext.Current != null)
                //{
                //    return HttpContext.Current.Server.MapPath(path) + Path.AltDirectorySeparatorChar;
                //}
                //TODO: add full path to exe application
                //string location = System.Reflection.Assembly.GetExecutingAssembly().Location.NormalizePath();
                string location = Assembly.GetExecutingAssembly().CodeBase.NormalizePath();

                const string fileProtocolString = "file:///";

                if (location.StartsWith(fileProtocolString))
                {
                    location = location.Remove(0, fileProtocolString.Length);
                }
                return
                    location.Substring(0, location.LastIndexOf(Path.AltDirectorySeparatorChar)) +
                    Path.AltDirectorySeparatorChar +
                    path +
                    Path.AltDirectorySeparatorChar;
            }
            if (path[path.Length - 1] != Path.AltDirectorySeparatorChar)
            {
                return path + Path.AltDirectorySeparatorChar;
            }
            return path;
        }

        /// <summary>
        /// Creates <see cref="System.Windows.Media.Imaging.BitmapSource"/> from <see cref="System.Drawing.Bitmap"/> image.
        /// </summary>
        /// <param name="source">Bitmap image.</param>
        /// <returns>BitmapSource.</returns>
        public static BitmapSource LoadBitmap(System.Drawing.Bitmap source)
        {
            return Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
        }

    }
}
